﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SilverTile;
using SilverTile.Keybard;

namespace SilverTileTests
{

    [TestClass]
    public class KeyboardHandlerTests
    {

        private KeyboardHandler _keyboardHandler;

        [TestInitialize]
        public void Setup()
        {
            _keyboardHandler = new KeyboardHandler(new Grid());
        }

        [TestMethod]
        public void KeyboardHandler_Should_Attach_To_KeyDown_And_KeyUp_Events()
        {

            //var uiElement = new DummyUIElement();
            //var keyboardHandler = new KeyboardHandler(uiElement);

            //Assert.IsTrue(uiElement.AttachedToKeyUp);
            //Assert.IsTrue(uiElement.AttachedToKeyDown);
            
        }

        [TestMethod]
        public void KeyboardHandler_Should_Activate_State_When_Key_Is_Pressed()
        {

            // Add a state that sets the stateActive variable to true when the left key is pressed
            bool stateActive = false;
            var keyState = new KeyState(Key.Left)
            {
                Activated = () => stateActive = true,
                Deactivated = () => stateActive = false
            };
            _keyboardHandler.AddState(keyState);

            // Press the left key down
            _keyboardHandler.KeyDown(Key.Left);
            Assert.IsTrue(stateActive, "Active action was not called");

            // Release the left key
            _keyboardHandler.KeyUp(Key.Left);
            Assert.IsFalse(stateActive, "Deactivate action was not called");

            // Press the up key
            _keyboardHandler.KeyDown(Key.Down);
            Assert.IsFalse(stateActive, "Action should not be activated");
            
        }

        [TestMethod]
        public void KeyboardHandler_Should_Activate_State_With_The_Right_Key_Combination()
        {

            var keyState = new KeyState(Key.Left, Key.Shift);
            bool stateActive = false;
            keyState.Activated = () => stateActive = true;
            keyState.Deactivated = () => stateActive = false;
            _keyboardHandler.AddState(keyState);

            // Press the left key down
            _keyboardHandler.KeyDown(Key.Left);
            Assert.IsFalse(stateActive, "State is activated when only Left is pressed");

            // Press the shift key down
            _keyboardHandler.KeyDown(Key.Shift);
            Assert.IsTrue(stateActive, "State is not activated when both Left and Shift are pressed");

            _keyboardHandler.KeyUp(Key.Left);
            Assert.IsFalse(stateActive, "State is activated after Left is released");

        }

        [TestMethod]
        public void KeyboardHandler_Should_Activate_All_States_That_Match_The_Pressed_Keys()
        {

            var leftState = new KeyState(Key.Left);
            var upState = new KeyState(Key.Up);

            _keyboardHandler.AddState(leftState);
            _keyboardHandler.AddState(upState);
            var upShiftState = _keyboardHandler.AddState(null, null, Key.Up, Key.Shift);
            
            _keyboardHandler.KeyDown(Key.Left);
            Assert.IsTrue(leftState.IsActive, "Left state is not active after Left is pressed");
            Assert.IsFalse(upState.IsActive, "Up state is active after Left is pressed");
            Assert.IsFalse(upShiftState.IsActive, "Up state is active after Left is pressed");

            _keyboardHandler.KeyDown(Key.Shift);
            Assert.IsTrue(leftState.IsActive, "Left state is not active after Left and Shift is pressed");
            Assert.IsFalse(upState.IsActive, "Up state is active after Left and Shift is pressed");
            Assert.IsFalse(upShiftState.IsActive, "Up state is active after Left and Shift is pressed");

            _keyboardHandler.KeyDown(Key.Up);
            Assert.IsTrue(leftState.IsActive, "Left state is not active after Left and Shift and Up is pressed");
            Assert.IsTrue(upState.IsActive, "Up state is not active after Left and Shift and Up is pressed");
            Assert.IsTrue(upShiftState.IsActive, "Up state is not active after Left and Shift and Up is pressed");
            
        }

        [TestMethod]
        public void KeyboardHandler_Should_Reactivate_All_Active_States_When_A_New_Button_Is_Pressed()
        {


            bool leftActive = false;
            bool upActive = false;

            var leftState = new KeyState(Key.Left);
            leftState.Activated = () => leftActive = true;
            var upState = new KeyState(Key.Up);
            upState.Activated = () => upActive = true;

            _keyboardHandler.AddState(leftState);            
            _keyboardHandler.AddState(upState);

            _keyboardHandler.KeyDown(Key.Left);
            _keyboardHandler.KeyDown(Key.Up);

            Assert.IsTrue(leftActive, "Left state is not active after Left and Up is pressed");
            Assert.IsTrue(upActive, "Up state is active after Left and Up is pressed");

            leftActive = false;
            upActive = false;

            _keyboardHandler.KeyDown(Key.Space); // Now the active actions should be called again

            Assert.IsTrue(leftActive, "Left active action was not called when a new button was pressed");
            Assert.IsTrue(upActive, "Up active action was not called when a new button was pressed");
            
        }

        [TestMethod]
        public void KeyboardHandler_Should_Deactivate_Inactive_Actions_Before_Activating_Active_Actions()
        {

            string sequence = string.Empty;

            var leftState = new KeyState(Key.Left);
            leftState.Activated = () => sequence += "LeftActivated ";
            leftState.Deactivated = () => sequence += "LeftDeactivated ";
            var upState = new KeyState(Key.Up);
            upState.Activated = () => sequence += "UpActivated ";
            upState.Deactivated = () => sequence += "UpDeactivated ";

            _keyboardHandler.AddState(leftState);
            _keyboardHandler.AddState(upState);

            _keyboardHandler.KeyDown(Key.Left);
            _keyboardHandler.KeyDown(Key.Up);

            Assert.AreEqual("LeftActivated LeftActivated UpActivated ", sequence, "Incorrect activation sequence after key down");

            _keyboardHandler.KeyUp(Key.Up);

            Assert.AreEqual("LeftActivated LeftActivated UpActivated UpDeactivated LeftActivated ", sequence, "Incorrect activation sequence after key up");
            
        }




    }
}
